<template>
  <div>
    <el-dialog
      v-model="dialogVisible"
      class="preView-img-dialog"
      :title="addForm.name"
    >
      <img
        v-if="fileList.length"
        style="height: 90%; margin: 0 auto"
        :src="imageUrl || ''"
        alt="Preview Image"
      />
    </el-dialog>
    <div>
      <el-dialog
        v-model="visible"
        :title="title"
        class="cpu-edit-dialog"
        destroy-on-close
      >
        <el-form
          ref="formRef"
          :model="form"
          :rules="rules"
          class="m-auto mt-1"
          label-position="right"
        >
          <el-form-item prop="val">
            <el-input v-model.trim="form['val']" />
          </el-form-item>
        </el-form>
        <template #footer>
          <el-button @click="visible = false">取 消</el-button>
          <el-button type="primary" @click="saveResourceData(title, form.val)">
            保存
          </el-button>
        </template>
      </el-dialog>
    </div>
    <div>
      <el-dialog
        v-model="netVisible"
        title="ipv4&网关"
        class="ip-edit-dialog"
        destroy-on-close
      >
        <el-form
          ref="formRef"
          :model="form"
          :rules="ipRules"
          class="m-auto mt-1"
          label-width="70px"
        >
          <el-form-item label="ipv4/cidr:" prop="ipV4">
            <el-input
              v-model.trim="form['ipV4']"
              placeholder="请按照0.0.0.0/0格式填写"
            />
          </el-form-item>
          <el-form-item label="网关:" prop="ipV4Gateway">
            <el-input v-model.trim="form['ipV4Gateway']" />
          </el-form-item>
        </el-form>
        <template #footer>
          <el-button @click="netVisible = false">取 消</el-button>
          <el-button
            type="primary"
            @click="saveNetWorkData(form.ipV4, form.ipV4Gateway)"
          >
            保存
          </el-button>
        </template>
      </el-dialog>
    </div>
    <div>
      <el-dialog
        v-model="dialogAclVisible"
        title="新增ACL"
        class="add-acl-dialog"
        align-center
      >
        <el-form ref="aclForm" :model="ACLParams" :rules="aclRules">
          <el-form-item label="协议：" prop="protocol">
            <el-select
              filterable
              clearable
              style="width: 100%"
              v-model="ACLParams.protocol"
            >
              <el-option
                v-for="item in protocolList"
                :key="item"
                :label="item"
                :value="item"
              >
              </el-option>
            </el-select>
          </el-form-item>

          <el-form-item label="优先级：" prop="priority">
            <el-input v-model.number="ACLParams.priority"></el-input>
          </el-form-item>
          <el-form-item label="源IP地址：" prop="sourceIP">
            <el-input v-model="ACLParams.sourceIP"></el-input>
          </el-form-item>
          <el-form-item label="目的IP地址：" prop="destinationIP">
            <el-input v-model="ACLParams.destinationIP"></el-input>
          </el-form-item>
          <el-form-item label="源MAC地址：" prop="sourceMAC">
            <el-input v-model="ACLParams.sourceMAC"></el-input>
          </el-form-item>
          <el-form-item label="目的MAC地址：" prop="destinationMAC">
            <el-input v-model="ACLParams.destinationMAC"></el-input>
          </el-form-item>
          <el-form-item label="动作：" prop="action">
            <el-select
              filterable
              clearable
              style="width: 100%"
              v-model="ACLParams.action"
            >
              <el-option label="正常转发" value="normal"> </el-option>
              <el-option label="丢弃" value="drop"> </el-option>
            </el-select>
          </el-form-item>
        </el-form>
        <template #footer>
          <span class="dialog-footer">
            <el-button @click="dialogAclVisible = false">取消</el-button>
            <el-button type="primary" @click="confrim"> 确定 </el-button>
          </span>
        </template>
      </el-dialog>
    </div>
    <div class="drawer" v-if="showVisible">
      <div class="moduleConfigTitle">
        <span>靶标配置</span>
        <el-icon @click="closeFunc" style="cursor: pointer"><Close /></el-icon>
      </div>
      <div class="target-set-content">
        <el-tabs v-model="activeName" @tab-change="handleChangeTab">
          <el-tab-pane
            label="基础配置"
            name="first"
            v-if="
              props.info.attrs.image.options.category !== 7 &&
              props.info.attrs.image.options.category !== 8
            "
          >
            <div class="basicConfig">
              <div class="basicConfig_title module-title">计算节点</div>
              <div style="margin: 5px 0 15px">
                <el-radio-group
                  v-model="addForm.computerID"
                  :disabled="
                    addForm.isGenerate == true ||
                    (addForm.instancePorts && addForm.instancePorts.length)
                  "
                >
                  <el-radio
                    :value="item.ID"
                    v-for="item in computers"
                    :key="item.ID"
                    >{{ item.name }}</el-radio
                  >
                </el-radio-group>
              </div>
              <div
                class="basicConfig_title module-title"
                v-if="props.info.attrs.image.options.category !== 10"
              >
                {{
                  props.info.attrs.image.options.category === 1
                    ? '虚拟机ID'
                    : props.info.attrs.image.options.category === 2
                    ? 'dockerID'
                    : '网桥'
                }}
              </div>
              <p
                class="basicConfig_title_p"
                v-if="props.info.attrs.image.options.category !== 10"
              >
                {{
                  addForm.bridge
                    ? addForm.bridge.name
                    : props.info.attrs.image.options.category === 2
                    ? addForm?.relevanceName?.substring(0, 8)
                    : addForm?.relevanceName
                }}
              </p>
              <div class="basicConfig_title module-title">基础信息</div>
              <div class="basicConfig_title_bg">
                <el-form
                  ref="formRef"
                  :rules="rules"
                  label-position="right"
                  :model="addForm"
                >
                  <el-form-item label="组件名称" prop="name">
                    <el-input v-model="addForm.name" />
                  </el-form-item>
                  <el-form-item
                    label="组件图片"
                    prop="file"
                    v-if="imageUrl !== '1'"
                  >
                    <el-upload
                      :auto-upload="false"
                      action="#"
                      class="avatar-uploader"
                      :on-change="validateFile"
                      accept=".png,.jpg"
                      :show-file-list="false"
                      :file-list="fileList"
                    >
                      <img
                        v-if="imageUrl"
                        :src="imageUrl"
                        class="avatar"
                        style="object-fit: contain"
                      />
                      <el-button v-else type="primary" size="mini"
                        >上传</el-button
                      >
                    </el-upload>
                  </el-form-item>
                  <el-form-item label=" ">
                    <div style="display: block">
                      <el-tooltip content="预览">
                        <el-icon color="#409EFF" class="pointer"
                          ><View @click="handlePreview"
                        /></el-icon>
                      </el-tooltip>
                    </div>
                  </el-form-item>
                </el-form>
              </div>
            </div>
          </el-tab-pane>
          <el-tab-pane
            label="实物配置"
            name="second"
            v-if="
              props.info.attrs.image.options.category === 7 ||
              props.info.attrs.image.options.category === 8
            "
          >
            <div class="basicConfig">
              <div class="basicConfig_title module-title">互联装置</div>
              <p style="margin: 20px 0">{{ addForm.relevanceName }}</p>
              <div class="basicConfig_title module-title">基础信息</div>
              <div style="margin: 20px 0 20px 10px">
                <el-form
                  ref="formRef"
                  :rules="rules"
                  label-position="right"
                  label-width="100px"
                  :model="addForm"
                  style="height: 280px"
                >
                  <el-form-item label="组件名称" prop="name">
                    <el-input v-model="addForm.name" />
                  </el-form-item>
                  <el-form-item label="实物IP">
                    <el-input disabled v-model="addForm.materialIP" />
                  </el-form-item>
                  <el-form-item label="实物MAC">
                    <el-input disabled v-model="addForm.materialMac" />
                  </el-form-item>
                  <el-form-item
                    label="组件图片"
                    prop="file"
                    v-if="imageUrl !== '1'"
                  >
                    <el-upload
                      :auto-upload="false"
                      action="#"
                      class="avatar-uploader"
                      :on-change="validateFile"
                      accept=".png,.jpg"
                      :show-file-list="false"
                      :file-list="fileList"
                    >
                      <img
                        v-if="imageUrl"
                        :src="imageUrl"
                        class="avatar"
                        style="object-fit: contain"
                      />
                      <el-button v-else type="primary" size="mini"
                        >上传</el-button
                      >
                    </el-upload>
                  </el-form-item>
                  <el-form-item>
                    <div style="display: block">
                      <el-tooltip content="预览">
                        <el-icon color="#409EFF" class="pointer"
                          ><View @click="handlePreview"
                        /></el-icon>
                      </el-tooltip>
                    </div>
                  </el-form-item>
                </el-form>
              </div>
            </div>
          </el-tab-pane>
          <el-tab-pane
            label="硬件配置"
            name="third"
            v-if="
              props.info.attrs.image.options.category !== 7 &&
              props.info.attrs.image.options.category !== 8 &&
              props.info.attrs.image.options.category !== 10
            "
          >
            <div>
              <div class="dockerConfig" style="padding-bottom: 10px">
                <div class="cpu flexStart" v-if="!isNet">
                  <div>
                    <el-icon>
                      <CpuIcon />
                    </el-icon>
                    <span class="title">CPU(c)</span>
                  </div>
                  <div class="data" @dblclick="changeInfo('CPU')">
                    <span v-text="`${addForm.oldCores || ''}`" />
                    <span
                      v-if="
                        !addForm.cores || addForm.oldCores !== addForm.cores
                      "
                      v-text="`（${addForm.cores || ''}）`"
                      style="color: red"
                    />
                  </div>
                </div>
                <div class="memory flexStart" v-if="!isNet">
                  <el-icon>
                    <MemoryIcon />
                  </el-icon>
                  <span class="title">内存(M)</span>
                  <div class="data" @dblclick="changeInfo('内存')">
                    <span v-text="addForm.oldMemory || ''" />
                    <span
                      v-if="
                        !addForm.memory || addForm.oldMemory !== addForm.memory
                      "
                      v-text="`（${addForm.memory || ''}）`"
                      style="color: red"
                    />
                  </div>
                </div>
                <div class="network flexStart">
                  <el-icon>
                    <NetWorkCardIcon />
                  </el-icon>
                  <span class="title">网卡</span>
                </div>
                <div
                  class="list"
                  :class="
                    item.status == 2
                      ? 'disabledList'
                      : item.status == 0 &&
                        (props.info.attrs.image.options.category === 1 ||
                          props.info.attrs.image.options.category === 2)
                      ? 'noCreatedList'
                      : ''
                  "
                  v-for="item in addForm.instancePorts"
                  :key="item.ID"
                >
                  <div class="flexStart flexStart_title">
                    <span>名称：</span>
                    <div v-text="`${item.name || ''}`" />
                  </div>
                  <div class="basicConfig_title_bgTwo">
                    <div class="flexStart" v-if="isNet == 2">
                      <span class="titleText">VLAN：</span>
                      <el-input
                        v-model="item.tag"
                        :disabled="item.status == 2"
                      ></el-input>
                    </div>
                    <div class="flexStart" v-if="!isNet">
                      <span class="titleText">mac地址：</span>
                      <div v-text="`${item.mac || ''}`" />
                    </div>
                    <div class="flexStart" v-if="!isNet">
                      <span class="titleText">ip类型：</span>
                      <div>
                        <el-radio-group
                          v-model="item.ipAllocationMode"
                          size="small"
                          :disabled="item.status == 2"
                        >
                          <el-radio-button :value="0">静态IP</el-radio-button>
                          <el-radio-button
                            v-show="item.materialConnectIPID === 0"
                            :value="1"
                            >DHCP</el-radio-button
                          >
                        </el-radio-group>
                      </div>
                    </div>
                    <div
                      class="flexStart"
                      v-if="
                        !isNet &&
                        (item.ipAllocationMode === 0 ||
                          item.ipAllocationMode === '0')
                      "
                      @dblclick="
                        item.status == 2 || item.materialConnectIPID !== 0
                          ? ''
                          : changeNetConfig('ipv4/cidr', item)
                      "
                    >
                      <span class="titleText">ipv4/cidr：</span>
                      <div style="position: relative; cursor: pointer">
                        <div v-text="`${item.oldIpV4 || ''}`" />
                        <div
                          v-if="!item.ipV4 || item.oldIpV4 !== item.ipV4"
                          v-text="`(${item.ipV4 || ''})`"
                          class="color_red"
                        />
                        <el-tooltip content="编辑">
                          <el-icon color="#409EFF" class="ip-edit-icon"
                            ><Edit @click="changeNetConfig('ipv4/cidr', item)"
                          /></el-icon>
                        </el-tooltip>
                      </div>
                    </div>
                    <div
                      class="flexStart"
                      v-if="
                        !isNet &&
                        (item.ipAllocationMode === 0 ||
                          item.ipAllocationMode === '0')
                      "
                      @dblclick="
                        item.status == 2 || item.materialConnectIPID !== 0
                          ? ''
                          : changeNetConfig('网关', item)
                      "
                    >
                      <span class="titleText">网关：</span>
                      <div style="position: relative; cursor: pointer">
                        <div v-text="`${item.oldIpV4Gateway || ''}`" />
                        <div
                          v-if="
                            !item.ipV4Gateway ||
                            item.oldIpV4Gateway !== item.ipV4Gateway
                          "
                          v-text="`(${item.ipV4Gateway || ''})`"
                          class="color_red"
                        />
                        <el-tooltip content="编辑">
                          <el-icon color="#409EFF" class="ip-edit-icon"
                            ><Edit @click="changeNetConfig('网关', item)"
                          /></el-icon>
                        </el-tooltip>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </el-tab-pane>
          <el-tab-pane
            label="网络服务"
            name="fourth"
            v-if="
              props.info &&
              props.info.attrs.image &&
              props.info.attrs.image.options &&
              props.info.attrs.image.options.category === 6
            "
          >
            <div class="basicConfig net_tab">
              <div class="basicConfig_title module-title">DHCP服务</div>
              <div style="margin: 20px 0 20px 10px">
                <el-form
                  ref="netFormRef"
                  :rules="rules"
                  label-position="right"
                  :model="addForm"
                  label-width="auto"
                >
                  <el-form-item label="" prop="name">
                    <el-switch
                      v-if="addForm.bridge?.isDHCPServer !== undefined"
                      v-model="addForm.bridge.isDHCPServer"
                      active-text="开启"
                      inactive-text="关闭"
                      :active-value="true"
                      :inactive-value="false"
                    >
                    </el-switch>
                  </el-form-item>
                  <div v-if="addForm?.bridge?.isDHCPServer === true">
                    <el-form-item
                      label="DHCP服务器IP/MASK"
                      prop="bridge.DHCPServer.ip"
                    >
                      <el-input
                        v-model="addForm['bridge']['DHCPServer'].ip"
                      ></el-input>
                    </el-form-item>
                    <el-form-item
                      label="地址池开始地址"
                      prop="bridge.DHCPServer.ipStart"
                    >
                      <el-input
                        v-model="addForm['bridge']['DHCPServer'].ipStart"
                      ></el-input>
                    </el-form-item>
                    <el-form-item
                      label="地址池结束地址"
                      prop="bridge.DHCPServer.ipEnd"
                    >
                      <el-input
                        v-model="addForm['bridge']['DHCPServer'].ipEnd"
                      ></el-input>
                    </el-form-item>
                    <el-form-item label="Vlan Tag" prop="bridge.DHCPServer.tag">
                      <el-input
                        v-model="addForm['bridge']['DHCPServer'].tag"
                        type="number"
                      ></el-input>
                    </el-form-item>
                  </div>
                </el-form>
              </div>

              <div class="module-header">
                <span class="basicConfig_title module-title">ACL管理</span>
                <button class="new-btn" @click="addACL">新增</button>
              </div>
              <div>
                <div class="module-content_table">
                  <table
                    class="acl-table acl-table-manage"
                    v-for="item in addForm['bridge'].NetworkACLRule"
                    :key="item.ID"
                  >
                    <tr>
                      <td>源IP</td>
                      <td>{{ item.sourceIP }}</td>
                      <td>目的IP</td>
                      <td>{{ item.destinationIP }}</td>
                    </tr>
                    <tr>
                      <td>优先级</td>
                      <td>{{ item.priority }}</td>
                      <td>协议</td>
                      <td>{{ item.protocol }}</td>
                    </tr>
                    <tr>
                      <td>源MAC</td>
                      <td>{{ item.sourceMAC }}</td>
                      <td>目的MAC</td>
                      <td>{{ item.destinationMAC }}</td>
                    </tr>
                    <tr>
                      <td>动作</td>
                      <td>
                        {{ item.action === 'normal' ? '正常转发' : '丢弃' }}
                      </td>
                      <td>操作</td>
                      <td
                        style="color: #f56c6c; cursor: pointer"
                        class="firewall-operation"
                      >
                        <el-icon
                          color="#F56C6C"
                          class="del_icon"
                          @click="removeACL(item)"
                        >
                          <Delete />
                        </el-icon>
                      </td>
                    </tr>
                  </table>
                </div>
              </div>
            </div>
          </el-tab-pane>
          <el-tab-pane
            label="文件上传"
            name="upload"
            v-if="
              props.info.attrs.image.options.category === 1 ||
              props.info.attrs.image.options.category === 2
            "
          >
            <div class="basicConfig net_tab">
              <div class="basicConfig_title module-title">文件上传</div>
              <div style="margin: 20px 0 20px 10px">
                <el-form
                  ref="sendFile"
                  label-position="right"
                  label-width="auto"
                >
                  <el-form-item label="选择文件" prop="username">
                    <el-upload
                      v-model:file-list="sendFileList"
                      :limit="1"
                      :on-change="uploadChange"
                    >
                      <el-button type="primary">选择文件</el-button>
                    </el-upload>
                  </el-form-item>
                  <el-form-item label="上传路径" prop="dstPath">
                    <el-input
                      v-if="props.info.attrs.image.options.category === 1"
                      v-model="sendFilePath"
                    >
                      <template #prepend>{{
                        addForm.os === 3 ? 'C:\\upload' : '/upload'
                      }}</template>
                    </el-input>
                    <el-input
                      v-if="props.info.attrs.image.options.category === 2"
                      v-model="sendFilePath"
                    >
                      <template #prepend>/upload</template>
                    </el-input>
                  </el-form-item>
                </el-form>
              </div>
            </div>
          </el-tab-pane>

          <el-tab-pane
            label="硬件配置"
            name="vpc-second"
            v-if="props.info.attrs.image.options.category === 10"
          >
            <div class="network flexStart">
              <el-icon>
                <NetWorkCardIcon />
              </el-icon>
              <span class="title">网卡</span>
            </div>
            <div
              class="list"
              :class="
                item.status == 2
                  ? 'disabledList'
                  : item.status == 0
                  ? 'noCreatedList'
                  : ''
              "
              v-for="item in addForm.instancePorts"
              :key="item.ID"
            >
              <div class="flexStart flexStart_title">
                <span>名称：</span>
                <div v-text="`${item.name || ''}`" />
              </div>
              <div class="basicConfig_title_bgTwo">
                <div class="flexStart" v-if="isNet == 2">
                  <span class="titleText">VLAN：</span>
                  <el-input
                    v-model="item.tag"
                    :disabled="item.status == 2"
                  ></el-input>
                </div>
                <div class="flexStart" v-if="!isNet">
                  <span class="titleText">mac地址：</span>
                  <div v-text="`${item.mac || ''}`" />
                </div>
                <div class="flexStart" v-if="!isNet">
                  <span class="titleText">ip类型：</span>
                  <div>
                    <el-radio-group
                      v-model="item.ipAllocationMode"
                      size="small"
                      :disabled="item.status == 2"
                    >
                      <el-radio-button :value="0">静态IP</el-radio-button>
                    </el-radio-group>
                  </div>
                </div>
                <div
                  class="flexStart"
                  v-if="
                    !isNet &&
                    (item.ipAllocationMode === 0 ||
                      item.ipAllocationMode === '0')
                  "
                  @dblclick="
                    item.status == 2 || item.materialConnectIPID !== 0
                      ? ''
                      : changeNetConfig('ipv4/cidr', item)
                  "
                >
                  <span class="titleText">ipv4/cidr：</span>
                  <div style="position: relative; cursor: pointer">
                    <div v-text="`${item.oldIpV4 || ''}`" />
                    <div
                      v-if="!item.ipV4 || item.oldIpV4 !== item.ipV4"
                      v-text="`(${item.ipV4 || ''})`"
                      class="color_red"
                    />
                    <el-tooltip content="编辑">
                      <el-icon color="#409EFF" class="ip-edit-icon"
                        ><Edit @click="changeNetConfig('ipv4/cidr', item)"
                      /></el-icon>
                    </el-tooltip>
                  </div>
                </div>
                <div
                  class="flexStart"
                  v-if="
                    !isNet &&
                    (item.ipAllocationMode === 0 ||
                      item.ipAllocationMode === '0')
                  "
                  @dblclick="
                    item.status == 2 || item.materialConnectIPID !== 0
                      ? ''
                      : changeNetConfig('网关', item)
                  "
                >
                  <span class="titleText">网关：</span>
                  <div style="position: relative; cursor: pointer">
                    <div v-text="`${item.oldIpV4Gateway || ''}`" />
                    <div
                      v-if="
                        !item.ipV4Gateway ||
                        item.oldIpV4Gateway !== item.ipV4Gateway
                      "
                      v-text="`(${item.ipV4Gateway || ''})`"
                      class="color_red"
                    />
                    <el-tooltip content="编辑">
                      <el-icon color="#409EFF" class="ip-edit-icon"
                        ><Edit @click="changeNetConfig('网关', item)"
                      /></el-icon>
                    </el-tooltip>
                  </div>
                </div>
                <div class="flexStart">
                  <span class="titleText">Vlan：</span>
                  <el-input type="number"
                            v-model.number="item.tag"
                            :disabled="item.status == 2"
                  ></el-input>
                </div>
              </div>
            </div>
          </el-tab-pane>
          <el-tab-pane
            label="网络服务"
            name="vpc-netService"
            v-if="props.info.attrs.image.options.category === 10"
          >
            <div>
              <div class="basicConfig net_tab">
                <div class="module-header">
                  <span class="basicConfig_title module-title">DHCP服务</span>
                  <button
                    class="new-btn"
                    v-if="addForm?.vpcInfo?.vpcID !== 0"
                    @click="addDHCP"
                  >
                    新增
                  </button>
                </div>
                <div class="module-content_table">
                  <table
                    class="acl-table dhcp-module-table"
                    v-for="item in dhcpList"
                    :key="item.ID"
                  >
                    <tr>
                      <td>DHCP服务器IP/MASK</td>
                      <td colspan="3">{{ item.ip }}</td>
                    </tr>
                    <tr>
                      <td>地址池开始地址</td>
                      <td colspan="3">{{ item.ipStart }}</td>
                    </tr>
                    <tr>
                      <td>地址池结束地址</td>
                      <td colspan="3">{{ item.ipEnd }}</td>
                    </tr>
                    <tr>
                      <td>Vlan</td>
                      <td>{{ item.tag }}</td>
                      <td>操作</td>
                      <td
                        style="color: #f56c6c; cursor: pointer"
                        class="firewall-operation"
                      >
                        <el-icon
                          color="#F56C6C"
                          class="del_icon"
                          @click="removeDHCP(item)"
                        >
                          <Delete />
                        </el-icon>
                      </td>
                    </tr>
                  </table>
                </div>
              </div>

              <!-- 路由服务独立部分 -->
              <div class="basicConfig net_tab routing-section">
                <div class="module-header">
                  <span class="basicConfig_title module-title">路由服务</span>
                </div>

                <div class="firewall-tabs route-service-tabs">
                  <div
                    class="firewall-tab"
                    :class="{ active: netServiceIndex === 0 }"
                    @click="getRouteConfigList"
                  >
                    路由配置
                  </div>
                  <div
                    class="firewall-tab"
                    :class="{ active: netServiceIndex === 1 }"
                    @click="getEffectiveRouteTableList"
                  >
                    生效路由表
                  </div>
                </div>

                <!-- 路由配置模块 -->
                <div
                  class="route-module"
                  :style="{ display: netServiceIndex === 0 ? 'block' : 'none' }"
                >
                  <div class="route-list-header">
                    <span class="route-list-title"
                      >路由配置列表（{{
                        addForm?.vpcInfo?.vpcID !== 0
                          ? routeConfigListTotal
                          : addForm?.vpcInfo?.staticRoutes?.length
                      }}）</span
                    >
                    <button
                      class="new-btn"
                      @click="addRouteConfig"
                      v-if="addForm?.vpcInfo?.vpcID !== 0"
                    >
                      新增
                    </button>
                  </div>
                  <table
                    class="acl-table router-config-table"
                    v-for="item in addForm?.vpcInfo?.vpcID !== 0
                      ? routeConfigList
                      : addForm?.vpcInfo?.staticRoutes
                      ? addForm?.vpcInfo?.staticRoutes
                      : []"
                    :key="item.ID"
                  >
                    <tr>
                      <td>IP地址/掩码</td>
                      <td colspan="3">{{ item.ipv4 }}</td>
                    </tr>
                    <tr>
                      <td>下一跳/接口</td>
                      <td colspan="3">{{ item.next }}</td>
                    </tr>
                    <tr>
                      <td>距离</td>
                      <td>{{ item.metric }}</td>
                      <td>操作</td>
                      <td style="color: #f56c6c; cursor: pointer">
                        <el-icon
                          color="#F56C6C"
                          class="del_icon"
                          @click="removeRouteConfig(item)"
                        >
                          <Delete />
                        </el-icon>
                      </td>
                    </tr>
                  </table>
                </div>

                <!-- 生效路由表模块 (默认隐藏) -->
                <div
                  class="route-module"
                  :style="{ display: netServiceIndex === 1 ? 'block' : 'none' }"
                >
                  <div class="route-list-header">
                    <span class="route-list-title"
                      >生效路由表列表（{{
                        effectiveRouteTableListTotal
                      }}）</span
                    >
                  </div>
                  <table
                    class="acl-table effective-route-table"
                    v-for="item in effectiveRouteTableList"
                    :key="item.ID"
                  >
                    <tr>
                      <td>目的地址</td>
                      <td>{{ item.destination }}</td>
                      <td>下一跳/接口</td>
                      <td>{{ item.gateway }}</td>
                    </tr>
                    <tr>
                      <td>标记</td>
                      <td>{{ item.flags }}</td>
                      <td>网络掩码</td>
                      <td>{{ item.genmask }}</td>
                    </tr>
                    <tr>
                      <td>路由距离</td>
                      <td>{{ item.metric }}</td>
                      <td>输出接口</td>
                      <td>{{ item.iface }}</td>
                    </tr>
                  </table>
                </div>
              </div>
            </div>
          </el-tab-pane>
          <el-tab-pane
            label="防火墙配置"
            name="vpc-firewall"
            v-if="props.info.attrs.image.options.category === 10"
          >
            <div>
              <div class="firewall-tabs">
                <div
                  class="firewall-tab"
                  :class="{ active: firewallIndex === 0 }"
                  @click="getAccessControlList"
                >
                  访问控制
                </div>
                <div
                  class="firewall-tab"
                  :class="{ active: firewallIndex === 1 }"
                  @click="getSourceNatList"
                >
                  源NAT
                </div>
                <div
                  class="firewall-tab"
                  :class="{ active: firewallIndex === 2 }"
                  @click="getPortMappingList"
                >
                  端口映射
                </div>
                <div
                  class="firewall-tab"
                  :class="{ active: firewallIndex === 3 }"
                  @click="getInboundStrategyList"
                >
                  入站策略
                </div>
              </div>

              <!-- 访问控制模块 -->
              <div
                class="module-content"
                :style="{ display: firewallIndex === 0 ? 'block' : 'none' }"
              >
                <div class="module-header">
                  <span class="module-title"
                    >访问控制列表（{{ accessControlListTotal }}）</span
                  >
                  <button
                    class="new-btn"
                    @click="addAccessControl"
                    v-if="addForm?.vpcInfo?.vpcID !== 0"
                  >
                    新增
                  </button>
                </div>
                <div class="module-content_table">
                  <table
                    class="acl-table"
                    v-for="item in accessControlList"
                    :key="item.ID"
                  >
                    <tr>
                      <td>源地址</td>
                      <td>{{ item.s_addr }}</td>
                      <td>目标地址</td>
                      <td>{{ item.d_addr }}</td>
                    </tr>
                    <tr>
                      <td>协议</td>
                      <td>{{ item.protocol }}</td>
                      <td>目的端口</td>
                      <td :title="item.d_port">
                        <span class="acl-table-d_port">{{ item.d_port }}</span>
                      </td>
                    </tr>
                    <tr>
                      <td>流入接口</td>
                      <td>{{ item.in_eth }}</td>
                      <td>流出接口</td>
                      <td>{{ item.out_eth }}</td>
                    </tr>
                    <tr>
                      <td>动作</td>
                      <td>{{ item.action }}</td>
                      <td>命中数</td>
                      <td>{{ item.pkts }}</td>
                    </tr>
                    <tr>
                      <td>命中字节</td>
                      <td>{{ item.bytes }}</td>
                      <td>操作</td>
                      <td
                        style="color: #f56c6c; cursor: pointer"
                        class="firewall-operation"
                      >
                        <el-icon
                          color="#4d70ff"
                          class="edit_icon"
                          @click="editAccessControl(item)"
                        >
                          <Edit />
                        </el-icon>
                        <el-icon
                          color="#F56C6C"
                          class="del_icon"
                          @click="removeAccessControl(item)"
                        >
                          <Delete />
                        </el-icon>
                        <img
                          src="@/assets/datang/firewall_up.png"
                          @click="moveStrategy(item, 'up')"
                          alt=""
                        />
                        <img
                          src="@/assets/datang/firewall_down.png"
                          @click="moveStrategy(item, 'down')"
                        />
                      </td>
                    </tr>
                  </table>
                </div>
              </div>

              <!-- 源NAT模块 (默认隐藏) -->
              <div
                class="module-content"
                :style="{ display: firewallIndex === 1 ? 'block' : 'none' }"
              >
                <div class="module-header">
                  <span class="module-title"
                    >源NAT列表（{{ sourceNatListTotal }}）</span
                  >
                  <button
                    class="new-btn"
                    @click="addSourceNat"
                    v-if="addForm?.vpcInfo?.vpcID !== 0"
                  >
                    新增
                  </button>
                </div>
                <div class="module-content_table">
                  <table
                    class="acl-table"
                    v-for="item in sourceNatList"
                    :key="item.ID"
                  >
                    <tr>
                      <td>源地址</td>
                      <td>{{ item.s_addr }}</td>
                      <td>目标地址</td>
                      <td>{{ item.d_addr }}</td>
                    </tr>
                    <tr>
                      <td>协议</td>
                      <td>{{ item.protocol }}</td>
                      <td>目的端口</td>
                      <td :title="item.d_port">
                        <span class="acl-table-d_port">{{ item.d_port }}</span>
                      </td>
                    </tr>
                    <tr>
                      <td>类型</td>
                      <td>
                        {{ item.action === 'MASQUERADE' ? '接口' : '地址' }}
                      </td>
                      <td>转化对象</td>
                      <td>{{ item.to_object }}</td>
                    </tr>
                    <tr>
                      <td>命中数</td>
                      <td>{{ item.pkts }}</td>
                      <td>命中字节</td>
                      <td>{{ item.bytes }}</td>
                    </tr>
                    <tr>
                      <td>操作</td>
                      <td
                        style="color: #f56c6c; cursor: pointer"
                        class="firewall-operation"
                      >
                        <el-icon
                          color="#4d70ff"
                          class="edit_icon"
                          @click="editSourceNat(item)"
                        >
                          <Edit />
                        </el-icon>
                        <el-icon
                          color="#F56C6C"
                          class="del_icon"
                          @click="removeSourceNat(item)"
                        >
                          <Delete />
                        </el-icon>
                        <img
                          src="@/assets/datang/firewall_up.png"
                          @click="moveStrategy(item, 'up')"
                          alt=""
                        />
                        <img
                          src="@/assets/datang/firewall_down.png"
                          @click="moveStrategy(item, 'down')"
                        />
                      </td>
                    </tr>
                  </table>
                </div>
              </div>

              <!-- 端口映射模块 (默认隐藏) -->
              <div
                class="module-content"
                :style="{ display: firewallIndex === 2 ? 'block' : 'none' }"
              >
                <div class="module-header">
                  <span class="module-title"
                    >端口映射列表（{{ portMappingListTotal }}）</span
                  >
                  <button
                    class="new-btn"
                    @click="addPortMapping"
                    v-if="addForm?.vpcInfo?.vpcID !== 0"
                  >
                    新增
                  </button>
                </div>
                <div class="module-content_table">
                  <table
                    class="acl-table"
                    v-for="item in portMappingList"
                    :key="item.ID"
                  >
                    <tr>
                      <td>协议</td>
                      <td>{{ item.protocol }}</td>
                      <td>外网端口</td>
                      <td>{{ item.out_port }}</td>
                    </tr>
                    <tr>
                      <td>内网IP</td>
                      <td>{{ item.in_ip }}</td>
                      <td>内网端口</td>
                      <td>{{ item.in_port }}</td>
                    </tr>
                    <tr>
                      <td>命中数</td>
                      <td>{{ item.pkts }}</td>
                      <td>命中字节</td>
                      <td>{{ item.bytes }}</td>
                    </tr>
                    <tr>
                      <td>操作</td>
                      <td
                        style="color: #f56c6c; cursor: pointer"
                        class="firewall-operation"
                      >
                        <el-icon
                          color="#4d70ff"
                          class="edit_icon"
                          @click="editPortMapping(item)"
                        >
                          <Edit />
                        </el-icon>
                        <el-icon
                          color="#F56C6C"
                          class="del_icon"
                          @click="removePortMapping(item)"
                        >
                          <Delete />
                        </el-icon>
                        <img
                          src="@/assets/datang/firewall_up.png"
                          @click="moveStrategy(item, 'up')"
                          alt=""
                        />
                        <img
                          src="@/assets/datang/firewall_down.png"
                          @click="moveStrategy(item, 'down')"
                        />
                      </td>
                    </tr>
                  </table>
                </div>
              </div>

              <!-- 入站模块 (默认隐藏) -->
              <div
                class="module-content"
                :style="{ display: firewallIndex === 3 ? 'block' : 'none' }"
              >
                <div class="module-header">
                  <span class="module-title"
                    >入站规则列表（{{ inboundStrategyListTotal }}）</span
                  >
                  <button
                    class="new-btn"
                    @click="addInboundStrategy"
                    v-if="addForm?.vpcInfo?.vpcID !== 0"
                  >
                    新增
                  </button>
                </div>
                <div class="module-content_table">
                  <table
                    class="acl-table"
                    v-for="item in inboundStrategyList"
                    :key="item.ID"
                  >
                    <tr>
                      <td>源地址</td>
                      <td>{{ item.s_addr }}</td>
                      <td>目标地址</td>
                      <td>{{ item.d_addr }}</td>
                    </tr>
                    <tr>
                      <td>协议</td>
                      <td>{{ item.protocol }}</td>
                      <td>目的端口</td>
                      <td :title="item.d_port">
                        <span class="acl-table-d_port">{{ item.d_port }}</span>
                      </td>
                    </tr>
                    <tr>
                      <td>流入接口</td>
                      <td>{{ item.in_eth }}</td>
                      <td>动作</td>
                      <td>{{ item.action }}</td>
                    </tr>
                    <tr>
                      <td>命中数</td>
                      <td>{{ item.pkts }}</td>
                      <td>命中字节</td>
                      <td>{{ item.bytes }}</td>
                    </tr>
                    <tr>
                      <td>操作</td>
                      <td
                        style="color: #f56c6c; cursor: pointer"
                        class="firewall-operation"
                      >
                        <el-icon
                          color="#4d70ff"
                          class="edit_icon"
                          @click="editInboundStrategy(item)"
                        >
                          <Edit />
                        </el-icon>
                        <el-icon
                          color="#F56C6C"
                          class="del_icon"
                          @click="removeInboundStrategy(item)"
                        >
                          <Delete />
                        </el-icon>
                        <img
                          src="@/assets/datang/firewall_up.png"
                          @click="moveStrategy(item, 'up')"
                          alt=""
                        />
                        <img
                          src="@/assets/datang/firewall_down.png"
                          @click="moveStrategy(item, 'down')"
                        />
                      </td>
                    </tr>
                  </table>
                </div>
              </div>
            </div>
          </el-tab-pane>
        </el-tabs>
      </div>
      <div class="drawer_footer">
        <div>
          <el-button @click="closeFunc">取消</el-button>
          <el-button
            type="primary"
            @click="
              saveFunc(
                activeName === 'fourth'
                  ? 'net'
                  : activeName === 'upload'
                  ? 'fileSend'
                  : '',
              )
            "
            >保存</el-button
          >
        </div>
      </div>
    </div>
  </div>

  <div>
    <el-dialog v-model="dhcpVisible" title="新建" class="add-vpc-DHCP-dialog">
      <el-form
        ref="dhcpFormRef"
        :rules="dhcpRules"
        label-position="right"
        :model="dhcpForm"
        class="sandbox-network-DHCP-form"
      >
        <el-form-item label="端口" prop="instancePortID">
          <el-select
            filterable
            v-model="dhcpForm.instancePortID"
            class="w-full"
            clearable
          >
            <el-option
              v-for="item in dhcpInstancesArr"
              :label="item.name"
              :value="item.ID"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="地址池开始地址" prop="ipStart">
          <el-input v-model="dhcpForm.ipStart"></el-input>
        </el-form-item>
        <el-form-item label="地址池结束地址" prop="ipEnd">
          <el-input v-model="dhcpForm.ipEnd"></el-input>
        </el-form-item>
        <el-form-item label="Vlan Tag" prop="Tag">
          <el-input-number v-model="dhcpForm.Tag"></el-input-number>
        </el-form-item>
      </el-form>
      <template #footer>
        <span>
          <el-button @click="dhcpVisible = false">取 消</el-button>
          <el-button type="primary" @click="addDHCPConfigData">
            新 建
          </el-button>
        </span>
      </template>
    </el-dialog>
  </div>

  <AddOrEditAccessControl @updateData="getAccessControlList" />
  <AddOrEditSourceNat @updateData="getSourceNatList" />
  <AddOrEditPortMapping @updateData="getPortMappingList" />
  <AddOrEditInboundStrategy @updateData="getInboundStrategyList" />
  <AddRouterConfig @updateData="getRouteConfigList" />
</template>

<script setup>
import { ref, computed, watch, reactive, isReadonly } from 'vue';
import {
  getCopyDescFunc,
  getDescFunc,
  instanceSendFile,
  setCopyDescFunc,
  setDescFunc,
  uploadMyGraphicsFile,
  getByID,
  deleteACL,
  addAcl
} from '@/api/topo/topo';
import { verifyIP, protocolList, IP_REGEXP } from '@/utils/common';
import { simulationCover } from '../defaultConfig';
import {
  getRouterConfigByVPCApi,
  delRouterConfigByVPCApi,
  getEffectRouterByVPCApi,
  delAccessControlByVPCApi,
  getAccessControlByVPCApi,
  editAccessControlByVPCApi,
  getSourceNatByVPCApi,
  delSourceNatByVPCApi,
  editSourceNatByVPCApi,
  getPortMappingByVPCApi,
  delPortMappingByVPCApi,
  editPortMappingByVPCApi,
  getInboundStrategyByVPCApi,
  delInboundStrategyByVPCApi,
  editInboundStrategyByVPCApi,
  getDHCPConfigApi,
  addDHCPConfigApi,
  delDHCPConfigApi,
} from '@/api/topo/vpc';
import { ElMessage, ElMessageBox } from 'element-plus';
import AddRouterConfig from '../vpcNetwork/children/addRouterConfig.vue';
import AddOrEditAccessControl from '../vpcNetwork/children/firewall/accessControl/addOrEdit.vue';
import AddOrEditSourceNat from '../vpcNetwork/children/firewall/sourceNat/addOrEdit.vue';
import AddOrEditPortMapping from '../vpcNetwork/children/firewall/portMapping/addOrEdit.vue';
import AddOrEditInboundStrategy from '../vpcNetwork/children/firewall/inboundStrategy/addOrEdit.vue';
import { emitter } from '@/utils/bus';

const formRef = ref(null);
const validateIP = (rule, value, callback) => {
  if (!value) return callback('IP不能为空');
  const par =
    /^((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])(?::(?:[0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?$/;
  const [ip, mask] = value.split('/');
  if (!par.test(ip)) return callback('请输入合法IP');
  const masks = /^(?:[1-9]|[12]\d|3[0-2])$/;
  if (!masks.test(mask)) {
    return callback('请输入合法掩码');
  }
  return callback();
};
const validateGateWay = (rule, value, callback) => {
  if (!value) return callback();
  const par =
    /^((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])(?::(?:[0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?$/;
  const tmp = value.split('/');
  if (!par.test(tmp[0])) return callback('请输入合法网关');
  return callback();
};
const emit = defineEmits(['closeDialog', 'editNode', 'refreshGraph']);
const props = defineProps({
  drawer: {
    default: function () {
      return null;
    },
    type: Boolean,
  },
  info: {
    default: function () {
      return {};
    },
    type: Object,
  },
  id: {
    default: function () {
      return '';
    },
    type: String,
  },
  cid: {
    default: function () {
      return '';
    },
    type: String,
  },
  clusId: {
    default: function () {
      return '';
    },
    type: String,
  },
});
const netFormRef = ref(null);
const activeName = ref('first');
const rules = {
  name: [{ required: true, trigger: 'blur', message: '名称不能为空' }],
  val: [{ required: true, trigger: 'blur', message: '不能为空' }],
  'bridge.DHCPServer.ip': [
    { required: true, trigger: 'blur', message: '不能为空' },
  ],
  'bridge.DHCPServer.ipStart': [
    { required: true, trigger: 'blur', message: '不能为空' },
  ],
  'bridge.DHCPServer.ipEnd': [
    { required: true, trigger: 'blur', message: '不能为空' },
  ],
};
const ipRules = {
  ipV4: [{ validator: validateIP, trigger: 'blur', required: true }],
  ipV4gateway: [
    { validator: validateGateWay, trigger: 'blur', required: false },
  ],
};
//详情修改
const visible = ref(false);
const netVisible = ref(false);
const form = ref({});
const title = ref('');
watch(
  () => props?.info,
  val => {
    sendFileList.value = [];
    getMyNodeList();
  },
  { immediate: false },
);
//图片
const dialogVisible = ref(false);
//文件列表
const fileList = ref([]);
// 上传文件的列表
const sendFileList = ref([]);
// 上传文件的路径
const sendFilePath = ref('');
//判断图片是否有修改
const fileVal = ref(null);
//图片地址
const imageUrl = ref(null);
const showVisible = computed(() => {
  if (props.drawer) {
    if (
      props.info.attrs.image.options.category !== 7 &&
      props.info.attrs.image.options.category !== 8
    ) {
      activeName.value = 'first';
    } else {
      activeName.value = 'second';
    }
  }
  return props.drawer;
});
const addForm = ref({});
const isNet = ref(false);
const computers = ref([]);
//ACL
const ACLList = ref([]);
const ACLParams = reactive({
  name: '',
  priority: null,
  sourceIP: '',
  destinationIP: '',
  protocol: '',
  sourceMAC: '',
  destinationMAC: '',
  action: 'normal',
  clusterNetworkID: null,
});
const aclForm = ref(null);
const dialogAclVisible = ref(false);
const verifyInfoIP = (rule, value, callback) => {
  // ip如果为空不检测
  if (value === '') {
    return callback();
  }
  return verifyIP(value) ? callback() : callback('IP不合法');
};

const uploadChange = rawFile => {
  sendFileList.value = [rawFile];
};

const aclRules = reactive({
  priority: [
    {
      required: true,
      type: 'number',
      message: '格式不正确,只能数字',
      trigger: 'blur',
    },
    {
      pattern: /^(?:0|[1-9][0-9]?|100)(\.[0-9]{0,2})?$/,
      message: '只能为0-100之间的整数',
    },
  ],
  sourceIP: [
    { message: '源IP地址不能为空', trigger: 'blur' },
    {
      trigger: 'blur',
      validator: verifyInfoIP,
    },
  ],
  destinationIP: [
    { message: '目的IP地址不能为空', trigger: 'blur' },
    {
      trigger: 'blur',
      validator: verifyInfoIP,
    },
  ],
  protocol: [{ required: true, message: '请选择协议', trigger: 'change' }],
  sourceMAC: [
    { message: '源MAC地址不能为空', trigger: 'blur' },
    {
      pattern:
        /^[A-Fa-f\d]{2}:[A-Fa-f\d]{2}:[A-Fa-f\d]{2}:[A-Fa-f\d]{2}:[A-Fa-f\d]{2}:[A-Fa-f\d]{2}$/,
      message: 'MAC不合法',
    },
  ],
  destinationMAC: [
    { message: '目的MAC地址不能为空', trigger: 'blur' },
    {
      pattern:
        /^[A-Fa-f\d]{2}:[A-Fa-f\d]{2}:[A-Fa-f\d]{2}:[A-Fa-f\d]{2}:[A-Fa-f\d]{2}:[A-Fa-f\d]{2}$/,
      message: 'MAC不合法',
    },
  ],
  action: [{ required: true, message: '请选择动作', trigger: 'change' }],
  clusterNetworkID: [
    { required: true, message: '请选择网络', trigger: 'change' },
  ],
});
//获取节点详情
const getMyNodeList = async () => {
  // activeName.value = 'first'
  let res;
  if (props.id) {
    res = await getDescFunc({ id: props.id, uuid: props.info.id });
  } else {
    res = await getCopyDescFunc({ id: props.cid, uuid: props.info.id });
  }
  if (props.info.attrs.image.options.category === 4) {
    // 集群网络
    isNet.value = 1;
  } else if (props.info.attrs.image.options.category === 6) {
    // 游离网桥
    isNet.value = 2;
  } else {
    isNet.value = 0;
  }
  fileList.value = [];
  sendFilePath.value = '';
  if (!(res instanceof Error)) {
    addForm.value = res.data;
    imageUrl.value = res.data['image'].startsWith('/')
      ? res.data['image']
      : '/' + res.data['image']; // 兼容之前未以斜杠录入的数据
    fileList.value.push({
      name: res.data.name,
      url: res.data['image'],
    });
    let nodeInfo = await getByID(props.clusId);
    if (!(nodeInfo instanceof Error)) {
      computers.value = nodeInfo.data.computers;
    }
  }

  // 获取最开始实例端口
  dhcpInstancePorts.value = addForm.value.instancePorts;
};
//修改红字
const changeInfo = async (flag, item) => {
  title.value = flag;
  if (flag == 'CPU') {
    form.value = { val: addForm.value['oldCores'] };
    visible.value = true;
  } else if (flag == '内存') {
    form.value = { val: addForm.value['oldMemory'] };
    visible.value = true;
  }
};
// 修改ip、网关
const changeNetConfig = async (flag, item) => {
  title.value = flag;
  netVisible.value = true;
  form.value = {
    ipV4: item['ipV4'],
    ipV4Gateway: item['ipV4Gateway'],
    ID: item.ID,
  };
};
const saveResourceData = async (title, value) => {
  if (title == 'CPU') {
    addForm.value['cores'] = value;
    visible.value = false;
  } else if (title == '内存') {
    addForm.value['memory'] = value;
    visible.value = false;
  }
  saveFunc();
};
const saveNetWorkData = async (ipv4, ipV4Gateway) => {
  formRef.value?.validate(async valid => {
    if (valid) {
      const index = addForm.value.instancePorts.findIndex(item => {
        return item['ID'] === form.value.ID;
      });
      addForm.value.instancePorts[index]['ipV4'] = ipv4;
      addForm.value.instancePorts[index]['ipV4Gateway'] = ipV4Gateway;
      await saveFunc();
      netVisible.value = false;
    }
  });
};
const closeFunc = () => {
  emit('closeDialog');
};
//上传图片
const validateFile = async file => {
  fileVal.value = file.raw;
  imageUrl.value = URL.createObjectURL(file.raw);
  fileList.value = [
    {
      name: file.name,
      url: URL.createObjectURL(file.raw),
    },
  ];
};
//保存
const saveFunc = async flag => {
  let arg = props.info;
  arg.attrs.text['text'] = addForm.value.name;
  if (flag == 'net') {
    netFormRef.value.validate(async valid => {
      if (valid) {
        await saveInfo(arg);
      }
    });
  } else if (flag === 'fileSend') {
    // 根据颜色判断是否开机
    if (arg.attrs['.rank'].fill !== '#67C23A') {
      ElMessage.warning('实例未开机');
      return;
    }
    if (sendFileList.value.length < 1) {
      ElMessage.warning('请选择文件');
      return;
    }
    const form = new FormData();
    form.append('file', sendFileList.value[0].raw);
    form.append('type', '1');

    if (props.info.attrs.image.options.category === 1) {
      if (addForm.value.os === 3) {
        // 使用正则表达式检验路径
        const regex = /^(\.\\|\.\.\\).*/;
        if (regex.test(sendFilePath.value)) {
          return ElMessage.error('文件路径不能以相对路径("..\\"或".\\")开头');
        }
      } else {
        // 使用正则表达式检验路径
        const regex = /^(\.\/|\.\.\/).*/;
        if (regex.test(sendFilePath.value)) {
          return ElMessage.error('文件路径不能以相对路径("../"或"./")开头');
        }
      }
    } else {
      // 使用正则表达式检验路径
      const regex = /^(\.\/|\.\.\/).*/;
      if (regex.test(sendFilePath.value)) {
        return ElMessage.error('文件路径不能以相对路径("../"或"./")开头');
      }
    }

    uploadMyGraphicsFile(form).then(resUpload => {
      ElMessage.success('文件上传完成，开始下发');

      instanceSendFile(props.id, props.info.id, {
        filePath: resUpload.data.file_path,
        dstPath: sendFilePath.value,
      }).then(res => {});
    });
  } else if (fileVal.value) {
    const formData = new FormData();
    formData.append('file', fileVal.value);
    const resUpload = await uploadMyGraphicsFile(formData);
    if (!(resUpload instanceof Error)) {
      arg.attrs.image['xlink:href'] = simulationCover(resUpload.data.file_path);
      fileList.value = [
        {
          name: resUpload.data.file_path,
          url: origin + '/' + resUpload.data.file_path,
        },
      ];
      await saveInfo(arg);
    }
  } else {
    if (!fileList.value.length) {
      arg.attrs.image['xlink:href'] = '';
    }
    await saveInfo(arg);
  }
};
const saveInfo = async arg => {
  let ports = [];
  if (isNet.value == 2 && addForm.value.instancePorts.length) {
    for (let i = 0; i < addForm.value.instancePorts.length; i++) {
      let item = addForm.value.instancePorts[i];
      let arg = {
        ID: item.ID,
        tag: Number(item.tag),
      };
      ports.push(arg);
    }
  }
  let data = {
    name: addForm.value.name,
    cores: Number(addForm.value.cores),
    memory: Number(addForm.value.memory),
    instancePort: isNet.value == 2 ? ports : addForm.value.instancePorts,
    id: props.id,
    uuid: props.info.id,
    image: arg.attrs.image['xlink:href'],
    computerID: addForm.value.computerID,
    isDHCPServer: addForm.value.bridge && addForm.value.bridge?.isDHCPServer,
    DHCPServer: addForm.value.bridge && addForm.value.bridge.DHCPServer,
  };
  // 将dhcp的tag转为int
  if (addForm.value?.bridge?.DHCPServer?.tag) {
    addForm.value.bridge.DHCPServer.tag = parseInt(
      addForm.value.bridge.DHCPServer.tag,
      10,
    );
  }
  let res;
  if (props.id) {
    res = await setDescFunc(data);
  } else {
    data.id = props.cid;
    res = await setCopyDescFunc(data);
  }
  if (!(res instanceof Error)) {
    ElMessage.success(`保存成功`);
    emit('editNode', arg, res.data.computerImage);
  }
};

//新增ACL
const addACL = () => {
  dialogAclVisible.value = true;
  Object.assign(ACLParams, {
    name: '',
    priority: null,
    sourceIP: '',
    destinationIP: '',
    protocol: '',
    sourceMAC: '',
    destinationMAC: '',
    action: 'normal',
    instanceID: addForm.value.ID,
  });
};

//新增确定回调
const confrim = async () => {
  aclForm.value?.validate(async valid => {
    if (valid) {
      await addAcl(ACLParams).then(res => {
        if (!(res instanceof Error)) {
          let nodeList = sessionStorage.getItem('nodeList');
          nodeList = JSON.parse(nodeList);
          nodeList[res.data.ID] = { ID: addForm.value.ID, options: 'acl' };
          sessionStorage.setItem('nodeList', JSON.stringify(nodeList));
          getMyNodeList();
        }
      });
      dialogAclVisible.value = false;
    }
  });
};

//删除ACL
const removeACL = async row => {
  await deleteACL(row.ID).then(res => {
    if (!(res instanceof Error)) {
      let nodeList = sessionStorage.getItem('nodeList');
      nodeList = JSON.parse(nodeList);
      nodeList[res.data.ID] = { ID: addForm.value.ID, options: 'acl' };
      sessionStorage.setItem('nodeList', JSON.stringify(nodeList));
      setTimeout(() => {
        getMyNodeList();
      }, 500);
    }
  });
};

const handlePreview = () => {
  dialogVisible.value = true;
};

// 切换tab
const handleChangeTab = tab => {
  if (tab === 'vpc-firewall') {
    getAccessControlList();
  } else if (tab === 'vpc-netService') {
    getDHCPConfigList();
    getRouteConfigList();
  }
};

// DHCP表单
const dhcpList = ref([]);
const dhcpTotal = ref(0);
const dhcpFormRef = ref();
const dhcpInstancesArr = ref([]);
const dhcpForm = reactive({
  ipStart: '',
  ipEnd: '',
  instancePortID: '',
  Tag: null,
});

const dhcpRules = {
  instancePortID: [
    {
      required: true,
      message: '请选择端口',
      trigger: ['change', 'blur'],
    },
  ],
  ipStart: [
    {
      required: true,
      message: '地址池开始地址不能为空',
      trigger: ['change', 'blur'],
    },
    {
      pattern: IP_REGEXP,
      message: '请输入合法IP',
      trigger: ['blur'],
    },
  ],
  ipEnd: [
    {
      required: true,
      message: '地址池结束地址不能为空',
      trigger: ['change', 'blur'],
    },
    {
      pattern: IP_REGEXP,
      message: '请输入合法IP',
      trigger: ['blur'],
    },
  ],
  Tag: [
    {
      required: true,
      message: 'Vlan Tag不能为空',
    },
  ],
};
const dhcpVisible = ref(false);
const dhcpInstancePorts = ref([]);

// 获取DHCP
const getDHCPConfigList = async () => {
  getDHCPConfigApi(props.id, props.info.id).then(res => {
    if (!(res instanceof Error)) {
      dhcpList.value = res.data;
      dhcpTotal.value = res.data?.length || 0;

      // 遍历数据
      let temp = [];
      dhcpInstancePorts.value.forEach(port => {
        // 遍历端口
        let flag = false;
        dhcpList.value.forEach(item => {
          if (port.ID === item.instancePortID) {
            item.ip = item.ip + '（' + port.name + '）';
            flag = true;
          }
        });

        if (!flag) {
          temp.push(port);
        }
      });

      dhcpInstancesArr.value = temp;
    }
  });
};

// 添加DHCP弹窗
const addDHCP = () => {
  dhcpVisible.value = true;
};

// 添加DHCP
const addDHCPConfigData = () => {
  dhcpFormRef.value.validate(async valid => {
    if (valid) {
      addDHCPConfigApi(props.id, props.info.id, dhcpForm).then(res => {
        if (!(res instanceof Error)) {
          ElMessage.success(`添加成功!`);
          dhcpVisible.value = false;
          getDHCPConfigList();
        }
      });
    }
  });
};

// 删除DHCP
const removeDHCP = async item => {
  ElMessageBox.confirm(`删除DHCP ，删除后将不可恢复！`, '删除DHCP', {
    confirmButtonText: '删 除',
    cancelButtonText: '取 消',
    type: 'warning',
    center: true,
    customClass: 'delMessageBox',
    confirmButtonClass: 'delButtonClass',
  }).then(async () => {
    delDHCPConfigApi(props.id, props.info.id, item.ID).then(res => {
      if (!(res instanceof Error)) {
        ElMessage.success(`删除成功!`);
        getDHCPConfigList();
      }
    });
  });
};

watch(
  dhcpVisible,
  () => {
    if (!dhcpVisible.value) {
      dhcpFormRef.value?.resetFields();
    }
  },
  { immediate: false },
);

// 路由下标
const netServiceIndex = ref(0);

// 路由配置模块定义字段
const routeConfigList = ref([]);
const routeConfigListTotal = ref(0);

// 获取路由配置模块
const getRouteConfigList = async () => {
  netServiceIndex.value = 0;

  if (addForm.value?.vpcInfo?.vpcID !== 0) {
    return getRouterConfigByVPCApi(addForm.value?.vpcInfo?.vpcID, {
      page: 1,
      pageSize: -1,
    }).then(res => {
      if (!(res instanceof Error)) {
        routeConfigList.value = res.data?.list || [];
        routeConfigListTotal.value = res.data?.total || 0;
      }
    });
  } else {
    routeConfigList.value = [];
    routeConfigListTotal.value = 0;
  }
};

// 添加路由配置
const addRouteConfig = () => {
  emitter.emit('addRouterConfig', { vpcID: addForm.value?.vpcInfo?.vpcID });
};

// 删除路由配置模块
const removeRouteConfig = async item => {
  ElMessageBox.confirm(`删除路由配置 ，删除后将不可恢复！`, '删除路由配置', {
    confirmButtonText: '删 除',
    cancelButtonText: '取 消',
    type: 'warning',
    center: true,
    customClass: 'delMessageBox',
    confirmButtonClass: 'delButtonClass',
  }).then(async () => {
    delRouterConfigByVPCApi(addForm.value?.vpcInfo?.vpcID, item.ID).then(
      res => {
        if (!(res instanceof Error)) {
          ElMessage.success(`删除成功!`);
          getRouteConfigList();
        }
      },
    );
  });
};

// 生效路由表定义字段
const effectiveRouteTableList = ref([]);
const effectiveRouteTableListTotal = ref(0);

// 获取生效路由表
const getEffectiveRouteTableList = async () => {
  netServiceIndex.value = 1;
  if (addForm.value?.vpcInfo?.vpcID !== 0) {
    return getEffectRouterByVPCApi(addForm.value?.vpcInfo?.vpcID, {
      page: 1,
      pageSize: -1,
    }).then(res => {
      if (!(res instanceof Error)) {
        effectiveRouteTableList.value = res.data || [];
        effectiveRouteTableListTotal.value = res.data?.length || 0;
      }
    });
  } else {
    effectiveRouteTableList.value = [];
    effectiveRouteTableListTotal.value = 0;
  }
};

// 防火墙下标
const firewallIndex = ref(0);

// 访问控制模块定义字段
const accessControlList = ref([]);
const accessControlListTotal = ref(0);

// 获取访问控制模块
const getAccessControlList = async () => {
  firewallIndex.value = 0;

  if (addForm.value?.vpcInfo?.vpcID !== 0) {
    return getAccessControlByVPCApi(addForm.value?.vpcInfo?.vpcID, {
      page: 1,
      pageSize: -1,
    }).then(res => {
      if (!(res instanceof Error)) {
        accessControlList.value = res.data?.list || [];
        accessControlListTotal.value = res.data?.total || 0;
      }
    });
  } else {
    accessControlList.value = [];
    accessControlListTotal.value = 0;
  }
};

/**
 * 新增访问控制
 */
const addAccessControl = () => {
  emitter.emit('addOrEditAccessControl', {
    vpcID: addForm.value?.vpcInfo?.vpcID,
  });
};

/**
 * 编辑访问控制
 */
const editAccessControl = item => {
  emitter.emit('addOrEditAccessControl', {
    editObj: item,
    vpcID: addForm.value?.vpcInfo?.vpcID,
  });
};

// 删除访问控制模块
const removeAccessControl = async item => {
  ElMessageBox.confirm(`删除访问控制 ，删除后将不可恢复！`, '删除访问控制', {
    confirmButtonText: '删 除',
    cancelButtonText: '取 消',
    type: 'warning',
    center: true,
    customClass: 'delMessageBox',
    confirmButtonClass: 'delButtonClass',
  }).then(async () => {
    delAccessControlByVPCApi(addForm.value?.vpcInfo?.vpcID, item.position).then(
      res => {
        if (!(res instanceof Error)) {
          ElMessage.success(`删除成功!`);
          getAccessControlList();
        }
      },
    );
  });
};

// 源NAT模块定义字段
const sourceNatList = ref([]);
const sourceNatListTotal = ref(0);

// 获取源NAT模块
const getSourceNatList = async () => {
  firewallIndex.value = 1;

  if (addForm.value?.vpcInfo?.vpcID !== 0) {
    return getSourceNatByVPCApi(addForm.value?.vpcInfo?.vpcID, {
      page: 1,
      pageSize: -1,
    }).then(res => {
      if (!(res instanceof Error)) {
        sourceNatList.value = res.data?.list || [];
        sourceNatListTotal.value = res.data?.total || 0;
      }
    });
  } else {
    sourceNatList.value = [];
    sourceNatListTotal.value = 0;
  }
};

/**
 * 新增源NAT
 */
const addSourceNat = () => {
  emitter.emit('addOrEditSourceNat', { vpcID: addForm.value?.vpcInfo?.vpcID });
};

/**
 * 编辑源NAT
 */
const editSourceNat = item => {
  emitter.emit('addOrEditSourceNat', {
    editObj: item,
    vpcID: addForm.value?.vpcInfo?.vpcID,
  });
};

// 删除源NAT模块
const removeSourceNat = async item => {
  ElMessageBox.confirm(`删除源NAT ，删除后将不可恢复！`, '删除源NAT', {
    confirmButtonText: '删 除',
    cancelButtonText: '取 消',
    type: 'warning',
    center: true,
    customClass: 'delMessageBox',
    confirmButtonClass: 'delButtonClass',
  }).then(async () => {
    delSourceNatByVPCApi(addForm.value?.vpcInfo?.vpcID, item.position).then(
      res => {
        if (!(res instanceof Error)) {
          ElMessage.success(`删除成功!`);
          getSourceNatList();
        }
      },
    );
  });
};

// 端口映射模块定义字段
const portMappingList = ref([]);
const portMappingListTotal = ref(0);
// 获取端口映射模块
const getPortMappingList = async () => {
  firewallIndex.value = 2;

  if (addForm.value?.vpcInfo?.vpcID !== 0) {
    return getPortMappingByVPCApi(addForm.value?.vpcInfo?.vpcID, {
      page: 1,
      pageSize: -1,
    }).then(res => {
      if (!(res instanceof Error)) {
        portMappingList.value = res.data?.list || [];
        portMappingListTotal.value = res.data?.total || 0;
      }
    });
  } else {
    portMappingList.value = [];
    portMappingListTotal.value = 0;
  }
};

/**
 * 新增端口映射
 */
const addPortMapping = () => {
  emitter.emit('addOrEditPortMapping', {
    vpcID: addForm.value?.vpcInfo?.vpcID,
  });
};

/**
 * 编辑端口映射
 */
const editPortMapping = item => {
  emitter.emit('addOrEditPortMapping', {
    editObj: item,
    vpcID: addForm.value?.vpcInfo?.vpcID,
  });
};

// 删除端口映射模块
const removePortMapping = async item => {
  ElMessageBox.confirm(`删除端口映射 ，删除后将不可恢复！`, '删除端口映射', {
    confirmButtonText: '删 除',
    cancelButtonText: '取 消',
    type: 'warning',
    center: true,
    customClass: 'delMessageBox',
    confirmButtonClass: 'delButtonClass',
  }).then(async () => {
    delPortMappingByVPCApi(addForm.value?.vpcInfo?.vpcID, item.position).then(
      res => {
        if (!(res instanceof Error)) {
          ElMessage.success(`删除成功!`);
          getPortMappingList();
        }
      },
    );
  });
};

// 入站模块定义字段
const inboundStrategyList = ref([]);
const inboundStrategyListTotal = ref(0);
// 获取入站模块
const getInboundStrategyList = async () => {
  firewallIndex.value = 3;

  if (addForm.value?.vpcInfo?.vpcID !== 0) {
    return getInboundStrategyByVPCApi(addForm.value?.vpcInfo?.vpcID, {
      page: 1,
      pageSize: -1,
    }).then(res => {
      if (!(res instanceof Error)) {
        inboundStrategyList.value = res.data?.list || [];
        inboundStrategyListTotal.value = res.data?.total || 0;
      }
    });
  } else {
    inboundStrategyList.value = [];
    inboundStrategyListTotal.value = 0;
  }
};

/**
 * 新增入站
 */
const addInboundStrategy = () => {
  emitter.emit('addOrEditInboundStrategy', {
    vpcID: addForm.value?.vpcInfo?.vpcID,
  });
};

/**
 * 编辑入站
 */
const editInboundStrategy = item => {
  emitter.emit('addOrEditInboundStrategy', {
    editObj: item,
    vpcID: addForm.value?.vpcInfo?.vpcID,
  });
};

// 删除入站模块
const removeInboundStrategy = async item => {
  ElMessageBox.confirm(`删除入站 ，删除后将不可恢复！`, '删除入站', {
    confirmButtonText: '删 除',
    cancelButtonText: '取 消',
    type: 'warning',
    center: true,
    customClass: 'delMessageBox',
    confirmButtonClass: 'delButtonClass',
  }).then(async () => {
    delInboundStrategyByVPCApi(
      addForm.value?.vpcInfo?.vpcID,
      item.position,
    ).then(res => {
      if (!(res instanceof Error)) {
        ElMessage.success(`删除成功!`);
        getInboundStrategyList();
      }
    });
  });
};

/**
 * 移动策略
 * @param item
 * @param type
 */
const moveStrategy = (item, type) => {
  ElMessageBox.confirm(`是否确定移动策略?`, '移动', {
    confirmButtonText: '确 定',
    cancelButtonText: '取 消',
    type: 'warning',
    center: true,
  }).then(async () => {
    if (firewallIndex.value === 0) {
      editAccessControlByVPCApi(addForm.value?.vpcInfo?.vpcID, item.position, {
        ...item,
        move: type,
      }).then(res => {
        if (!(res instanceof Error)) {
          ElMessage.success('移动成功');
          getAccessControlList();
        }
      });
    } else if (firewallIndex.value === 1) {
      editSourceNatByVPCApi(addForm.value?.vpcInfo?.vpcID, item.position, {
        ...item,
        move: type,
      }).then(res => {
        if (!(res instanceof Error)) {
          ElMessage.success('移动成功');
          getSourceNatList();
        }
      });
    } else if (firewallIndex.value === 2) {
      editPortMappingByVPCApi(addForm.value?.vpcInfo?.vpcID, item.position, {
        ...item,
        move: type,
      }).then(res => {
        if (!(res instanceof Error)) {
          ElMessage.success('移动成功');
          getPortMappingList();
        }
      });
    } else if (firewallIndex.value === 3) {
      editInboundStrategyByVPCApi(
        addForm.value?.vpcInfo?.vpcID,
        item.position,
        {
          ...item,
          move: type,
        },
      ).then(res => {
        if (!(res instanceof Error)) {
          ElMessage.success('移动成功');
          getInboundStrategyList();
        }
      });
    }
  });
};

defineExpose({
  getMyNodeList,
});
</script>

<style lang="scss">
.net_tab {
  .el-form-item__label {
    word-break: keep-all;
  }
  .el-descriptions {
    border: 1px solid #ccc;
    padding: 10px;
    border-radius: 5px;
    box-sizing: border-box;
    margin-top: 5px;
    .del_icon {
      font-size: 20px;
      cursor: pointer;
    }
  }
  .flexBetween {
    display: flex;
    align-items: center;
    justify-content: space-between;
  }
}
.drawer {
  position: absolute;
  top: 50%;
  transition: all 0.5s;
  width: 400px;
  //padding: 10px;
  right: 0px;
  transform: translateY(-50%);
  height: 83.5%;
  background: #0b3367;
  border-radius: 5px;
  box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.12);
  box-sizing: border-box;
  z-index: 9999;
  color: #fff;
  .color_red {
    color: #f56c6c;
  }
  .avatar-uploader {
    padding: 10px 20px;
    background-color: #002554;
    border: 1px solid #1158a8;
    border-radius: 4px;
  }
  .avatar {
    width: 100px;
    height: 100px;
  }
  .el-tabs__content {
    overflow-y: auto !important;
    overflow-x: auto !important;
  }
  .moduleConfigTitle {
    border-bottom: 1px solid #1158a8;
    padding: 10px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 14px;
  }
  .basicConfig {
    height: 100%;
    //overflow: scroll;
    // .basicConfig_title {
    //   border-left: 5px solid #0e4eee;
    //   padding-left: 0px;
    // }

    .basicConfig_title_p {
      margin: 15px 0 20px;
      overflow-wrap: break-word;
      min-height: 32px;
      background-color: #002554;
      border: 1px solid #1158a8;
      border-radius: 4px;
      padding: 0 10px;
      line-height: 32px;
    }

    .basicConfig_title_bg {
      margin: 15px 0 10px;
      background-color: #002554;
      border: 1px solid #1158a8;
      border-radius: 4px;
      padding: 15px 10px 15px 0;
    }
  }
  .flexStart {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    padding: 7px 0;
    box-sizing: border-box;
    .data {
      position: absolute;
      right: 40px;
      text-align: right;
      cursor: pointer;
    }
    .title {
      margin-left: 5px;
    }
    .titleText {
      width: 30%;
      text-align: right;
    }

    .ip-edit-icon {
      cursor: pointer;
      position: absolute;
      right: -24px;
      top: 50%;
      transform: translateY(-50%);
      font-size: 18px;
    }
  }

  .basicConfig_title_bgTwo {
    margin: 15px 0 10px;
    background-color: #002554;
    border: 1px solid #1158a8;
    border-radius: 4px;
    padding: 10px 15px;
  }

  .basicConfig_title_bgThree {
    background-color: #002554;
    border: 1px solid #1158a8;
    margin: 20px 0;
  }

  .pointer {
    cursor: pointer;
  }
  .network,
  .cpu,
  .memory {
    padding: 0 20px;
    height: 40px;
    line-height: 40px;
    margin-top: 10px;
    background-color: #002554;
  }

  .memory .el-icon {
    width: 16px;
    height: 16px;

    svg {
      width: 16px;
      height: 16px;
    }
  }

  .list {
    margin-top: 5px;
    padding: 5px;
  }

  .disabledList {
    border: 1px dashed #f56c6c;
    cursor: not-allowed;
  }

  .noCreatedList {
    border: 1px solid #f56c6c;
  }

  .drawer_footer {
    text-align: right;

    div {
      margin-right: 20px;
    }
  }
}
</style>
<style lang="scss" scoped>
:deep(.ip-edit-dialog) {
  width: 560px;
  .el-form {
    max-width: 460px;
    .el-form-item__label {
      width: 70px;
    }
  }
}

:deep(.cpu-edit-dialog) {
  width: 560px;
  .el-form {
    max-width: 460px;
    .el-form-item__label {
      width: 0;
    }
  }
}

:deep(.preView-img-dialog) {
  width: 560px;
  padding-bottom: 10px;
}

:deep(.add-acl-dialog) {
  width: 560px;
  .el-form {
    max-width: 460px;
    .el-form-item__label {
      width: 130px;
    }
  }
}

.firewall-tabs {
  display: flex;
  padding: 10px 0 0;
  gap: 10px;
  flex-wrap: wrap;
}

.firewall-tab {
  padding: 10px 15px;
  border-radius: 10px;
  cursor: pointer;
  color: #718096;
  font-size: 13px;
  transition: all 0.3s;
  box-shadow: 4px 4px 8px #d1d9e6, -4px -4px 8px #ffffff;
  position: relative;
  overflow: hidden;
}

.firewall-tab:hover {
  color: #3182ce;
  transform: translateY(-2px);
}

.firewall-tab.active {
  color: #ffffff;
  font-weight: 500;
}

.firewall-tab.active::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: linear-gradient(135deg, #3182ce, #63b3ed);
  border-radius: 10px;
  z-index: -1;
  animation: fadeIn 0.3s ease-out;
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.module-content {
  padding: 20px 0;
}

.module-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.module-title {
  font-size: 15px;
  color: #2d3748;
  font-weight: 600;
  position: relative;
  padding-left: 12px;
}

.module-title::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 4px;
  height: 16px;
  background: linear-gradient(to bottom, #3182ce, #63b3ed);
  border-radius: 4px;
}

.module-content_table {
  overflow-y: auto;
  max-height: 320px;
}

.acl-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  border-radius: 10px;
  background: #e8f3fc;
  box-shadow: 4px 4px 8px #d1d9e6, -4px -4px 8px #ffffff;
  overflow: hidden;
  margin-bottom: 0.12rem;
}

.acl-table td {
  padding: 12px 0;
  font-size: 13px;
  color: #4a5568;
  border-bottom: 1px solid #d1d9e6;
}

.acl-table tr:last-child td {
  border-bottom: none;
}

.acl-table td:nth-child(odd) {
  color: #718096;
  font-weight: 600;
  text-align: right;
  background-color: #d7ebfc;
  padding-right: 12px;
}

.acl-table td:nth-child(even) {
  color: #2d3748;
  font-weight: 500;
  padding-left: 10px;
}

.acl-table-d_port {
  display: inline-block;
  max-width: 50px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.router-config-table {
  border: 1px solid #d1d9e6;
  box-shadow: none;

  tr td:first-child {
    width: 100px;
  }

  tr td:nth-child(3) {
    width: 60px;
  }
}

.effective-route-table {
  tr td:nth-child(1) {
    width: 80px;
  }

  tr td:nth-child(2) {
    width: 100px;
  }

  tr td:nth-child(3) {
    width: 100px;
  }

  tr td:nth-child(4) {
    width: 108px;
  }
}

.acl-table-manage {
  tr td:nth-child(1) {
    width: 80px;
  }

  tr td:nth-child(2) {
    width: 108px;
  }

  tr td:nth-child(3) {
    width: 100px;
  }

  tr td:nth-child(4) {
    width: 108px;
  }
}

.dhcp-module-table {
  tr td:nth-child(1) {
    width: 180px;
  }

  tr td:nth-child(3) {
    width: 60px;
  }
}

.new-btn {
  padding: 8px 18px;
  color: #3182ce;
  border: none;
  border-radius: 10px;
  cursor: pointer;
  font-size: 13px;
  font-weight: 500;
  transition: all 0.3s;
  display: flex;
  align-items: center;
}

.new-btn::before {
  content: '+';
  margin-right: 6px;
  font-size: 16px;
  font-weight: 600;
}

.routing-section {
  margin-top: 16px;
}

.route-service-tabs {
  margin-top: -10px;
  margin-bottom: 20px;
}

.route-list-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.route-list-title {
  font-size: 14px;
  color: #2d3748;
  font-weight: 500;
  position: relative;
}

.route-module {
  background-color: #e8f3fc;
  border-radius: 8px;
  padding: 12px;
  margin-top: 8px;
}

.firewall-operation {
  img {
    display: inline-block;
    vertical-align: baseline;
    margin-left: 6px;
  }

  .edit_icon {
    font-size: 20px;
    cursor: pointer;
    margin-right: 6px;
  }
}

:deep(.add-vpc-DHCP-dialog) {
  width: 560px;
  .el-form {
    max-width: 480px;
    .el-form-item__label {
      width: 160px;
    }
  }
}

.target-set-content {
  width: 100%;
  height: calc(100% - 86px);
  padding: 0 20px 30px;
}

:deep(.basicConfig_title_bg) {
  .el-form {
    height: 220px;

    .el-form-item__label {
      width: 100px;
    }
  }
}
</style>
